﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Timers;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Net;
using System.Net.NetworkInformation;
using System.Configuration;
using System.Resources;

namespace VPNMonitor
{
	public partial class VPNMonitor
	{
		System.Timers.Timer timer;

		public VPNMonitor()
		{
			Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));

			Logger.Log("Стартуем...");
			InitializeComponent();
		}

		void timer_Elapsed(object sender, ElapsedEventArgs e)
		{
			TestConnection();
		}

		private bool PingHost(string hostName)
		{
			try
			{
				if (hostName == null)
					return false;

				Ping p = new Ping();
				PingReply reply = p.Send(hostName);
				if (reply.Status != IPStatus.Success)
				{
					Logger.Log("Результат пинга хоста " + hostName + ": " + reply.Status.ToString(), LogLevel.Warning);
					return false;
				}
				else
					return true;
			}
			catch (Exception ex)
			{
				Logger.Log("Ошибка при пинге хоста " + hostName + " (соединение " + ConfigurationManager.AppSettings["ConnectionName"] + "): " + ex.Message, LogLevel.Error);
				
				return false;
			}
		}

		private void TestConnection()
		{
			TestConnection(GetTestAttempsCount, GetTestAttempsInterval);
		}

		private int GetTestAttempsCount
		{
			get
			{
				if (ConfigurationManager.AppSettings["TestAttemptsCount"] != null && ConfigurationManager.AppSettings["TestAttemptsCount"].Length > 0)
					return Convert.ToInt32(ConfigurationManager.AppSettings["TestAttemptsCount"]);
				else
					return 1;
			}
		}

		private int GetTestAttempsInterval
		{
			get
			{
				if (ConfigurationManager.AppSettings["TestAttemptsInterval"] != null && ConfigurationManager.AppSettings["TestAttemptsInterval"].Length > 0)
					return Convert.ToInt32(ConfigurationManager.AppSettings["TestAttemptsInterval"]);
				else
					return 0;
			}
		}

		private void TestConnection(int attemptsCount, int attempsInterval)
		{
			for (int i = 0; i < attemptsCount; i++)
			{
				if (PingHost(ConfigurationManager.AppSettings["TestHost"]))
					return;
				else if (PingHost(ConfigurationManager.AppSettings["TestHost2"]))
					return;

				if (i < attemptsCount - 1)
				{
					Thread.Sleep(attempsInterval);
					Logger.Log("Предыдущий тест был неудачным! Начинаем повторную проверку соединения (попытка № " + (i + 1).ToString() + ").. ", LogLevel.Warning);
				}
			}

			Logger.Log("Текущее соединение с " + ConfigurationManager.AppSettings["ConnectionName"] + " не обнаружено или работает с ошибками, соединяемся.. " , LogLevel.Error);
			
			VNPConnect();
		}

		/// <summary>
		/// Hard reconnect
		/// </summary>
		private void VNPConnect()
		{
			VNPConnect(true);
		}

		/// <summary>
		/// Connect or hard reconnect (if need)
		/// </summary>
		private void VNPConnect(bool breakCurrentConnection)
		{
			Process p;

			if (breakCurrentConnection)
			{
				try
				{
					// отключим подвисшее соединение
					p = new Process();
					p.StartInfo.CreateNoWindow = true;
					p.StartInfo.FileName = @"C:\Windows\system32\rasdial.exe";
					p.StartInfo.Arguments = ConfigurationManager.AppSettings["ConnectionName"] + " /DISCONNECT";
					p.Start();
					Thread.Sleep(1000);
				}
				catch
				{
				}
			}

			try
			{
				p = new Process();
				p.StartInfo.CreateNoWindow = true;
				p.StartInfo.FileName = @"C:\Windows\system32\rasdial.exe";
				p.StartInfo.Arguments = ConfigurationManager.AppSettings["ConnectionName"] + " " + ConfigurationManager.AppSettings["Login"] + " " + ConfigurationManager.AppSettings["Password"];
				p.Start();
			}
			catch (Exception ex)
			{
				Logger.Log("Ошибка при соединении с " + ConfigurationManager.AppSettings["ConnectionName"] + ".. " + ex.Message, LogLevel.Error);
			}
		}

		public void Start()
		{
			Logger.Log("Стартуем VPN monitor... ");

			VNPConnect(false);
			TestConnection();

			timer = new System.Timers.Timer(Convert.ToDouble(ConfigurationManager.AppSettings["Period"])); 
			timer.AutoReset = true;
			timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
			timer.Start();
		}

		public void Stop()
		{
			Logger.Log("Останавливаем VPN monitor... ");
		}

	}
}
